import logging

from aiogram import types
from aiogram_dialog import DialogManager
from fluentogram import TranslatorRunner

from src.application.category.service import CategoryService
from src.application.order.enums import OrderPeriod, OrderType
from src.application.order.service import OrderService
from src.application.proxy.service import ProxyService
from src.application.server.enums import ServerPrivacy, ServerType
from src.application.user.service import UserService
from src.infrastructure.date_helpers import get_date_time
from src.infrastructure.db.services.stats import update_stats
from src.infrastructure.utils.helpers import get_expiring_on

logger = logging.getLogger(__name__)


async def set_country_id(_, __, manager: DialogManager, country_id: str):
    manager.dialog_data["country_id"] = int(country_id)
    await manager.next()


async def set_category_id(_, __, manager: DialogManager, category_id: str):
    manager.dialog_data["category_id"] = int(category_id)
    await manager.next()


async def add_order(call: types.CallbackQuery, _, manager: DialogManager):
    """Создаем заказ для всех типов товаров (прокси, впн, подписка)"""

    user_service: UserService = manager.middleware_data.get("user_service")
    order_service: OrderService = manager.middleware_data.get("order_service")
    proxy_service: ProxyService = manager.middleware_data.get("proxy_service")
    category_service: CategoryService = manager.middleware_data.get("category_service")

    locale: TranslatorRunner = manager.middleware_data.get("locale")

    order_summ: float = manager.dialog_data.get("order_summ")

    user_id: int = call.from_user.id
    user = await user_service.get_user_by_id(user_id)

    # TODO вынести проверку в юзкейс создания заказа
    if user.balance < order_summ:
        await call.answer(locale.get("not-enough-balance", balance=user.balance))
        return

    selected_amount: int = manager.dialog_data.get("selected_amount")
    category_id: int = manager.dialog_data.get("category_id")
    period: OrderPeriod = getattr(OrderPeriod, manager.dialog_data.get("period"))
    proxy_type: str = manager.dialog_data.get("proxy_type")
    proxy_privacy: str = manager.dialog_data.get("proxy_privacy")
    country_id: int = manager.dialog_data.get("country_id")
    provider_id: int = manager.dialog_data.get("provider_id")
    site_id: int = manager.dialog_data.get("site_id")
    vpn_server_id: int = manager.dialog_data.get("vpn_server_id")

    cur_date = get_date_time()

    expiring_on = await get_expiring_on(cur_date, period)

    if category_id:
        category = await category_service.get_category_by_id(category_id)
    else:
        category = await category_service.get_category_for_private(country_id, provider_id)

    available_proxies = await proxy_service.get_available_proxies(
        proxy_type=getattr(ServerType, proxy_type),
        proxy_privacy=getattr(ServerPrivacy, proxy_privacy),
        country_id=country_id,
        provider_id=provider_id,
        category_id=category.id,
        site_id=site_id,
        limit=selected_amount,
        tg_user_id=user_id,
    )

    if selected_amount > available_proxies.total:
        await call.answer(locale.get("available-proxies-amount-changed", amount=available_proxies.total))
        return

    await order_service.create_order(
        tg_id=user_id,
        order_type=OrderType.proxy,
        order_summ=order_summ,
        category_id=category_id,
        period=period,
        proxies=available_proxies.proxies,
        country_id=country_id,
        provider_id=provider_id,
        site_id=site_id,
        vpn_server_id=vpn_server_id,
        expiring_on=expiring_on,
    )

    if manager.start_data and manager.start_data.get("for_test"):
        await user_service.set_test_proxy_acquired(tg_user_id=user_id, test_proxy_acquired=cur_date)

    if proxy_type == ServerType.mobile:
        await update_stats(db_session, mobile_proxies_bought=available_proxies.total)
    elif proxy_type == ServerType.mobile:
        await update_stats(db_session, server_proxies_bought=available_proxies.total)

    await call.answer(locale.get("order-success"))
    await manager.next()


async def add_order_vpn(call: types.CallbackQuery, _, manager: DialogManager):
    locale: TranslatorRunner = manager.middleware_data.get("locale")
    db_session = manager.middleware_data.get("db_session")

    subscription_summ: float = manager.dialog_data.get("subscription_summ")

    user_id: int = call.from_user.id
    user = await get_user(db_session, user_id)

    if user.balance < subscription_summ:
        await call.answer(locale.get("not-enough-balance", balance=user.balance))
        return

    period: str = manager.dialog_data.get("subscription_period")

    date_now = get_date_time()

    expiring_on = await get_expiring_on(date_now, getattr(OrderPeriod, period))

    category = await get_category_by_name(db_session, "Подписка")
    order = OrderModel(
        type="subscription",
        user_id=user_id,
        proxies=[],
        summ=subscription_summ,
        period=period,
        category_id=category.id,
        expiring_on=expiring_on,
    )

    order = await create_order(db_session, **order.dict())

    await update_stats(db_session, subscriptions=1)
    await call.answer(locale.get("order-success"))
    await db_session.commit()
    logger.info(f"Добавлена новая подписка {order.id}")
    await manager.done()
